package net.njcp.mybatis.frame.utils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName MapUtil
 * @Description: Map对象相互转换的工具类
 * @Author 柳拓
 * @Date 2019/8/23
 * @Version V1.0
 **/
public class MapUtil {

    public static Map<String,Object> Obj2Map(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<String, Object>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            if(field.get(obj) != null && !"serialVersionUID".equals(field.getName())){
                map.put(field.getName(), field.get(obj));
            }
        }
        return map;
    }

    public static <T> T map2Obj(Map<String,Object> map,Class<T> clz) throws Exception{
        T obj = clz.newInstance();
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        String keyFieldName = ReflectUtil.getPrimaryKey(clz);
        for(Field field:declaredFields){
            int mod = field.getModifiers();
            if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
                continue;
            }
            field.setAccessible(true);
            String fieldType = field.getType().getName();
            String dbFieldName = MatchesUtil.switchParam(field.getName()).toUpperCase();
            //判断是否为基本类型
            if(fieldType.contains("java.lang")){
                if(map.get(dbFieldName) != null){
                    //如果是java的包装类型，通过字符串构造一个对象，避免出现类型转换错误
                    String value = map.get(dbFieldName).toString();
                    field.set(obj, getFieldResult(field.getType(), value));
                }else if(map.get(field.getName()) != null){
                    //如果是java的包装类型，通过字符串构造一个对象，避免出现类型转换错误
                    String value = map.get(field.getName()).toString();
                    field.set(obj, getFieldResult(field.getType(), value));
                }
            }else {
                if(map.get(dbFieldName) != null){
                    //如果是其它类型，直接赋值对象
                    field.set(obj, map.get(dbFieldName));
                }else if(map.get(field.getName()) != null) {
                    //如果是其它类型，直接赋值对象
                    field.set(obj, map.get(field.getName()));
                }else{
                    //如果为空，可能为联合主键属性，够着主键对象
                    if (keyFieldName.equals(field.getName())){
                        field.set(obj, map2Obj(map, field.getType()));
                    }
                }
            }
        }
        return obj;
    }

    //根据解析的结果，构造一个字段一样数据类型的对象
    public static Object getFieldResult(Class<?> fieldType, String value){
        Object fieldObject = null;
        try {
            Constructor<?> cons = null;
            try {
                cons = fieldType.getConstructor(String.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            try {
                fieldObject = cons.newInstance(value);
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return fieldObject;
    }

}
